﻿using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

using BaseThing.Engine;
using Box2D.XNA;


namespace BaseThing.Game
{

    class Hero : GameObject
    {
        enum DIR
        {
            LEFT = 0,
            RIGHT
        };

        Sprite heroSpr = null;
                                       //Row, Col
                                       //Start, End
        Point walkAnimation    = new Point(1, 8);
        Point jumpAnimation = new Point(6, 9);
 
        DIR lastDir = DIR.LEFT;
        Point[] idleAnimations;

        World physicsWorld;
        Body body;
        int tWidth;
        int tHeight;
        int speed = 200;
        bool isJumping = false;

        KeyboardState currentKeyboardState, prevKeyboardState;

        public Hero(Vector2 Position,World physxWorld) : base()
        {
            this.physicsWorld = physxWorld;

            heroSpr = new Sprite(@"Textures/walk", 8, 1,15);
            heroSpr.Position = Position;
            this.Position = Position;

           
            heroSpr.SpriteEffects = SpriteEffects.None;
            AddSprite(heroSpr);

            //Idle Animations
            idleAnimations = new Point[2];

            idleAnimations[0] = new Point(3, 3); //LeftIdle
            idleAnimations[1] = new Point(3, 3); //RightIdle


            heroSpr.SetAnimation(idleAnimations[0]);

            tWidth = heroSpr.GetBounds().Width;
            tHeight = heroSpr.GetBounds().Height;
            CreatePolygonBody();


        }

        private void CreateBoxBody()
        {

            //Rectangle shape
            PolygonShape shape = new PolygonShape();
            shape.SetAsBox(tWidth / 2, tHeight/2);

            //Properties
            FixtureDef fd = new FixtureDef();
            fd.shape = shape;
            fd.density = 10;
            fd.friction = 2.5f;

            //Properties
            BodyDef bd = new BodyDef();
            bd.type = BodyType.Dynamic;
            bd.position = this.Position;

            //MassData
            MassData mass = new MassData();
            mass.mass = 100;

            //Creating the Body
            body = physicsWorld.CreateBody(bd);
            body.CreateFixture(fd);
            body.SetUserData("HERO");
          // body.SetMassData(ref mass);

        }

        private void CreatePolygonBody()
        {

            //Poly shape
            CircularList<Vector2> vertices = new CircularList<Vector2>();
            List<List<Vector2>> triangles;

            vertices.Add(new Vector2(4, 12)); 
            vertices.Add(new Vector2(9, 3)); 
            vertices.Add(new Vector2(19, 1)); 
            vertices.Add(new Vector2(32, 6)); 
            vertices.Add(new Vector2(34, 15)); 
            vertices.Add(new Vector2(30, 27)); 
            vertices.Add(new Vector2(46, 27)); 
            vertices.Add(new Vector2(46, 63)); 
            vertices.Add(new Vector2(11, 63)); 
            vertices.Add(new Vector2(11, 35)); 
            vertices.Add(new Vector2(5, 25));

            PolygonShape shape;

            triangles = GeometryFactory.EarClip(vertices);

            //Properties
            BodyDef bd = new BodyDef();
            bd.type = BodyType.Dynamic;
            bd.position = this.Position;


            //MassData
            MassData mass = new MassData();
            mass.mass = 25000;
            mass.center = new Vector2(tWidth / 2, tHeight / 2);

            //Creating the Body
            body = physicsWorld.CreateBody(bd);

            foreach (List<Vector2> triangle in triangles)
            {
                shape = new PolygonShape();
                shape.Set(triangle.ToArray(), triangle.Count);

                FixtureDef fd   = new FixtureDef();
                fd.shape = shape;
                fd.density = 10 * triangles.Capacity;
                fd.friction = 2.5f;

                body.CreateFixture(fd);
              
            }

            
            body.SetUserData("HERO");
            body.SetMassData(ref mass);
            //body.SetActive(false);
    

        }

        public override void Update(GameTime gameTime)
        {

            bool keyPressed = false;
            currentKeyboardState = Keyboard.GetState();

            if (currentKeyboardState.IsKeyDown(Keys.D))
                {
                    heroSpr.SetAnimation(walkAnimation);
                    heroSpr.SpriteEffects = SpriteEffects.None;
                  //  Move(new Vector2(1, 0));
                    body.SetLinearVelocity(new Vector2(speed, 0));
                    lastDir = DIR.RIGHT;
                    keyPressed = true;
                }

            if (currentKeyboardState.IsKeyDown(Keys.A))
                {
                    heroSpr.SetAnimation(walkAnimation);
                    heroSpr.SpriteEffects = SpriteEffects.FlipHorizontally;
                 //   Move(new Vector2(-1, 0));
                    body.SetLinearVelocity(new Vector2(-speed, 0));
                    lastDir = DIR.LEFT;
                    keyPressed = true;
                }

            if (currentKeyboardState.IsKeyDown(Keys.Space)
                && !prevKeyboardState.IsKeyDown(Keys.Space)
                )
                {
                    heroSpr.SetAnimation(jumpAnimation);
                   // body.ApplyLinearImpulse(new Vector2(0, -100),body.Position);
                    body.SetLinearVelocity(new Vector2(0, -speed) );
                    keyPressed = true;
                    isJumping = true;
                }

                if (!keyPressed && !isJumping)
                {
                    //heroSpr.SetAnimation(idleAnimations[(int)lastDir]);
                    heroSpr.Stop(idleAnimations[(int)lastDir].X);
                }

                if (isJumping && heroSpr.Status == SpriteState.END)
                {
                    isJumping = false;
                }

                //Updating the Position to the Sprite and object
                this.Position = body.Position;//new Vector2(body.Position.X - (tWidth / 2), body.Position.Y - (tHeight / 2));
                heroSpr.Position = this.Position;
                body.Rotation = 0;

              prevKeyboardState =  currentKeyboardState;
             base.Update(gameTime);
        }

        public override void Draw(SpriteBatch spriteBatch)
        {
            
            base.Draw(spriteBatch);
        }
    }
}
